Skip to content

Add a Once primitive #11187

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jan 1, 2014
Merged

Add a Once primitive #11187

merged 2 commits into from
Jan 1, 2014

Conversation

alexcrichton
Copy link
Member

Rationale can be found in the first commit, but this is basically the same thing as pthread_once

Of the 8 static mutexes that are currently in-use by the compiler and its
libraries, 4 of them are currently used for one-time initialization. The
unforunate side effect of using a static mutex is that the mutex is leaked.

This primitive should provide the basis for efficiently keeping track of
one-time initialization as well as ensuring that it does not leak the internal
mutex that is used.

I have chosen to put this in libstd because libstd is currently making use of a
static initialization mutex (rt::local_ptr), but I can also see a more refined
version of this type being suitable to initialize FFI bindings (such as
initializing LLVM and initializing winsock networking on windows). I also intend
on adding "helper threads" to libnative, and those will greatly benefit from a
simple "once" primitive rather than always reinventing the wheel by using
mutexes and bools.

I would much rather see this primitive built on a mutex that blocks green
threads appropriately, but that does not exist at this time, so it does not
belong outside of `std::unstable`.
@thestinger
Copy link
Contributor

A pthread_mutex_t can be statically initialized without any function calls. A lock takes 2 atomic operations so adding more overhead is significant. Why not just statically initialize them?

@alexcrichton
Copy link
Member Author

You are correct. This is not a perf-sensitive piece of code, if you're invoking a Once in a tight loop you should probably figure out how to refactor it outside of that tight loop. Other than that we do not have statically initialized mutexes right now (in the same sense of statically initialized pthread mutexes), and we would have to find a solution for windows before guaranteeing that a mutex is no allocations.

Regardless, a Once primitive is useful to have as an encapsulation that logic should run once and only once.

@brson
Copy link
Contributor

brson commented Dec 29, 2013

This might be better called Lazy<T> since it's doing lazy initialization. Once has other connotations in Rust.

@brson
Copy link
Contributor

brson commented Dec 29, 2013

Maybe lazy.get() instead of doit

@brson
Copy link
Contributor

brson commented Dec 29, 2013

Oh, I didn't realize this was mutex-specific.

@brson
Copy link
Contributor

brson commented Dec 29, 2013

I should have read the code before commenting. Now I understand what this is about.

I'm not sure that this is appropriate in init since it implies that init may be called more than once, while cleanup has no such promise. Having multiple threads calling init/destroy pairs seems like a recipe for disaster. What's the intent here?

@thestinger
Copy link
Contributor

@alexcrichton: It seems to me that Rust should stop being overly opinionated and let you initialize statics as you can in C++. It's a significant performance hit to need branches like this in every function using some globally initialized state. The work has to happen at some point, so why not run it before main and avoid branching everywhere?

@alexcrichton
Copy link
Member Author

Let's discuss life before main in a different issue, that is not the topic of this pull request.

@brson, no particular reason to use a Once in runtime initialization, it probably shouldn't (as you've noted) as it's not intended to be called concurrently.

@alexcrichton
Copy link
Member Author

Updated to remove the usage of Once during init, it's just totally unsynchronized now (because it expects one and only one caller)

bors added a commit that referenced this pull request Jan 1, 2014
Rationale can be found in the first commit, but this is basically the same thing as `pthread_once`
@bors bors closed this Jan 1, 2014
@bors bors merged commit c22fed9 into rust-lang:master Jan 1, 2014
@alexcrichton alexcrichton deleted the once branch January 1, 2014 21:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants